package com.huathy.autoGSDoc;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.CollectionListModel;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 生成属性的get set方法，并将属性上的注释添加到方法上
 * 生成带有返回值的get方法。用于链式编程
 * Created by Huathy on 15/8/15.
 */
public class AutoGSActionWithBuilder extends AnAction {

    private static final String GET = "获取";
    private static final String SET = "设置";

    @Override
    public void actionPerformed(AnActionEvent e) {
        generateGSMethod(getPsiMethodFromContext(e));
    }

    /**
     * 启动写线程
     *
     * @param psiMethod
     */
    private void generateGSMethod(final PsiClass psiMethod) {
        new WriteCommandAction.Simple(psiMethod.getProject(), psiMethod.getContainingFile()) {
            @Override
            protected void run() throws Throwable {
                createGetSet(psiMethod);
            }
        }.execute();
    }

    private void createGetSet(PsiClass psiClass) {
        List<PsiField> fields = new CollectionListModel<PsiField>(psiClass.getFields()).getItems();
        if (fields == null) {
            return;
        }
        List<PsiMethod> list = new CollectionListModel<PsiMethod>(psiClass.getMethods()).getItems();
        Set<String> methodSet = new HashSet<String>();
        for (PsiMethod m : list) {
            methodSet.add(m.getName());
        }
        PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(psiClass.getProject());

        for (PsiField field : fields) {
            if (field.getModifierList().hasModifierProperty(PsiModifier.FINAL)) {
                continue;
            }
            String methodText = buildGet(field);
            PsiMethod toMethod = elementFactory.createMethodFromText(methodText, psiClass);
            if (methodSet.contains(toMethod.getName())) {
                continue;
            }
            psiClass.add(toMethod);

            methodText = buildSet(field,psiClass);
            elementFactory = JavaPsiFacade.getElementFactory(psiClass.getProject());
            toMethod = elementFactory.createMethodFromText(methodText, psiClass);
            if (methodSet.contains(toMethod)) {
                continue;
            }
            psiClass.add(toMethod);
        }
    }

    private String buildGet(PsiField field) {
        StringBuilder sb = new StringBuilder();
        String doc = format(GET, field);
        if (doc != null) {
            sb.append(doc);
        }
        sb.append("public ");
        //判断字段是否是static
        if (field.getModifierList().hasModifierProperty(PsiModifier.STATIC)) {
            sb.append("static ");
        }
        sb.append(field.getType().getPresentableText() + " ");
        if (field.getType().getPresentableText().equals("boolean")) {
            sb.append("is");
        } else {
            sb.append("get");
        }
        sb.append(getFirstUpperCase(field.getName()));
        sb.append("(){\n");
        sb.append(" return this." + field.getName() + ";}\n");

        return sb.toString();
    }

    private String buildSet(PsiField field, PsiClass psiClass) {
        StringBuilder sb = new StringBuilder();
        String doc = format(GET, field);
        if (doc != null) {
            sb.append(doc);
        }
        sb.append("public ");
        //判断字段是否是static
        if (field.getModifierList().hasModifierProperty(PsiModifier.STATIC)) {
            sb.append("static ");
        }
//        sb.append("void ");
		sb.append(psiClass.getName() + " ");
		sb.append("set" + getFirstUpperCase(field.getName()));
        sb.append("(" + field.getType().getPresentableText() + " " + field.getName() + "){\n");
        sb.append("this." + field.getName() + " = " + field.getName() + ";");
        sb.append(" return this;}\n");
        return sb.toString();
    }

    private String getFirstUpperCase(String oldStr) {
        return oldStr.substring(0, 1).toUpperCase() + oldStr.substring(1);
    }

    private PsiClass getPsiMethodFromContext(AnActionEvent e) {
        PsiElement elementAt = getPsiElement(e);
        if (elementAt == null) {
            return null;

        }
        return PsiTreeUtil.getParentOfType(elementAt, PsiClass.class);
    }

    private PsiElement getPsiElement(AnActionEvent e) {
        PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE);
        Editor editor = e.getData(PlatformDataKeys.EDITOR);
        if (psiFile == null || editor == null) {
            e.getPresentation().setEnabled(false);
            return null;
        }
        //用来获取当前光标处的PsiElement
        int offset = editor.getCaretModel().getOffset();
        return psiFile.findElementAt(offset);
    }

    private String format(String string, PsiField field) {
        String oldContent;
        if (field.getDocComment() == null) {
            oldContent = field.getText().substring(0, field.getText().lastIndexOf("\n") + 1);
        } else {
            oldContent = field.getDocComment().getText();
        }
        if (oldContent.startsWith("//")) {
            oldContent = oldContent.replace("// ", "// " + string + " ");
        } else if (oldContent.startsWith("/**")) {
            String content = oldContent.replace("/**\n", "").replace("*/", "").replace("\n", "").trim();
            oldContent = oldContent.replace(content, content.replace("* ", "* " + string + " "));
        }
        return oldContent;
    }


}
